package com.fingard.dsp.distribute.payfree01;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.diagnostics.LogHelper;
import com.fingard.dsp.distribute.dstrbset.DstrbItem;
import com.fingard.io.FileHelper;
import com.fingard.net.TcpReceiver;
import com.fingard.net.WebRequest;
import com.fingard.text.StringHelper;

public class PAYFREE01Dispatcher implements Runnable{
	private DstrbItem dstrbItem;
	//private int listenType = 0;
	//private int portType = 0;
	private Socket clientSocket;

	public PAYFREE01Dispatcher(DstrbItem p_dstrbItem, Socket p_socket) {
		dstrbItem = p_dstrbItem;
		//listenType = p_listenType;
		//portType=p_portType;
		clientSocket = p_socket;
	}
	
	public int listenPort = 0;
	public int seqIDInner = 0;
	
	public void run() {
		try {
			doRequest();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private String getCharsetBank(){
		if(StringHelper.hasAnyChar(dstrbItem.charsetForBank)){
			return dstrbItem.charsetForBank;
		}
		else if(StringHelper.hasAnyChar(dstrbItem.charset)){
			return dstrbItem.charset;
		}
		return "GB2312";
	}
	
	private String getCharsetGateway(){
		if(StringHelper.hasAnyChar(dstrbItem.charsetForGateway)){
			return dstrbItem.charsetForGateway;
		}
		else if(StringHelper.hasAnyChar(dstrbItem.charset)){
			return dstrbItem.charset;
		}
		return "UTF-8";
	}
	
	private TcpReceiver recBytesFromSocket(Socket p_socket, StringBuilder p_sb){
		TcpReceiver retReceiver = new TcpReceiver();
		try {
			InputStream tmpInput = p_socket.getInputStream();
			
			retReceiver.recBytes = new byte[20480];//20K
			int tmpOffSet = 0;
            
			while(!retReceiver.isCompleted){
				int tmpReadLen = tmpInput.read(retReceiver.recBytes, tmpOffSet, retReceiver.recBytes.length - tmpOffSet);
				if(tmpReadLen<=0){
					break;
				}
				tmpOffSet += tmpReadLen;
				retReceiver.readedLength = retReceiver.readedLength + tmpReadLen;
				if(retReceiver.contentLength == -1){
					//通讯头部
					if(retReceiver.readedLength>=4){
						String tmpHead = new String(retReceiver.recBytes,0,4,getCharsetBank());
						try{
							retReceiver.contentLength = Integer.parseInt(tmpHead);
							retReceiver.contentStartIndex = 4;
						}
						catch(Exception ex){
							ex.printStackTrace();
						}
						
					}
				}
				
				if (retReceiver.contentLength > 0)
                {
                    if (retReceiver.recBytes.length < retReceiver.contentLength + retReceiver.contentStartIndex)
                    {
                        byte[] tmpUnionInfo = new byte[retReceiver.contentLength + retReceiver.contentStartIndex];//一次性分配内存
        				System.arraycopy(retReceiver.recBytes, 0, tmpUnionInfo, 0, tmpOffSet);
        				retReceiver.recBytes = null;
        				retReceiver.recBytes = tmpUnionInfo;
                    }
                    
                    int tmpToReadLen = retReceiver.contentLength + retReceiver.contentStartIndex - tmpOffSet;
                    if (tmpToReadLen <= 0)
                    {
                    	retReceiver.isCompleted = true;
                    	break;
                    }
                }
				else{
                	break;
				}
			}
		}
		catch (IOException e) {
			//e.printStackTrace();
			p_sb.append(LogHelper.getStackTrace(e)+"\r\n");
			retReceiver.connMsg = e.getMessage();
		}
		return retReceiver;
	}
	

	private static AtomicInteger concurrentNum = new AtomicInteger();
	private static int maxConcurrent = 0;
	private static Date maxHappenedTime = new Date();

	private void doRequest() throws Exception{
		
		int tmpConcurrentNum = concurrentNum.incrementAndGet();
		if(tmpConcurrentNum>maxConcurrent){
			maxConcurrent=tmpConcurrentNum;
			maxHappenedTime = new Date();
		    System.out.println("侦听端口"+listenPort+"当前并发数："+tmpConcurrentNum);
		}
		Date tmpTimeNow = new Date();
		StringBuilder sbLog = new StringBuilder();
		try {			
			sbLog.append(Format.DateTimeSSSFormat.format(tmpTimeNow)+" 1.开始接收\r\n");
			
			TcpReceiver recClient = recBytesFromSocket(clientSocket, sbLog);
			if(recClient.readedLength==0){//recClient.readedLength==0是F5等探测
				clientSocket.close();
				clientSocket = null;
				return;
			}
			String tmpStrRec = new String(recClient.recBytes,0,recClient.readedLength,getCharsetBank());
			sbLog.append(Format.DateTimeSSSFormat.format(new Date())+" 1.接收到请求"+recClient.readedLength+"字节："+tmpStrRec+"\r\n转发至："+dstrbItem.gatewayUrl+"\r\n");

			WebRequest tmpWebRequest = new WebRequest(dstrbItem.gatewayUrl);
			//tmpWebRequest.setConnectTimeout(60000);
			//tmpWebRequest.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			tmpWebRequest.setRequestProperty("connection", "Close");
			byte[] tmpUpBytes = tmpStrRec.getBytes(getCharsetGateway());
			String[] backStr = tmpWebRequest.upload(tmpUpBytes, getCharsetGateway());
			sbLog.append(Format.DateTimeSSSFormat.format(new Date())+" 3.返回："+backStr[1]+"\r\n");
			String respToClient = backStr[1].trim();
			sbLog.append(Format.DateTimeSSSFormat.format(new Date())+" 4.trim()之后返回："+backStr[1]+"\r\n");
			byte[] respBytes = respToClient.getBytes(getCharsetBank());
			

			OutputStream tmpOutput = clientSocket.getOutputStream();
			tmpOutput.write(respBytes, 0, respBytes.length);
			tmpOutput.close();
			clientSocket.close();
			clientSocket = null;

		} catch (IOException e) {
			//e.printStackTrace();
			sbLog.append(LogHelper.getStackTrace(e)+"\r\n");
		}
		finally{

			tmpConcurrentNum = concurrentNum.decrementAndGet();
			if(tmpConcurrentNum==0){
				Date tmpTimeFin = new Date();
				long tmpMilSeconds = tmpTimeFin.getTime() - maxHappenedTime.getTime();
				long tmpSeconds = tmpMilSeconds / 1000;
				if(tmpSeconds>=60){
					maxConcurrent =0 ;
					System.out.println("当前并发数："+tmpConcurrentNum);
				}
			}
			if(clientSocket != null){
				clientSocket.close();
			}
		}
		try{
		String tmpStrLogSeq = String.format("%04d", seqIDInner);
		String tmpDateDir = Format.DateForLogFormat.format(tmpTimeNow).replace("-", File.separator);
		String tmpLogFile = FGBiz.distributor.logsDirPath+File.separator+dstrbItem.dstrbCode+"Logs"+File.separator+tmpDateDir+File.separator+listenPort+"_"+Format.DateTime14Format.format(tmpTimeNow)+"_"+tmpStrLogSeq+".txt";
		FileHelper.writeFile(tmpLogFile, sbLog);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
